package com.personal.gateway.flinkAllCommand.configurationOption.configurationType;

import com.alibaba.fastjson.JSONObject;
import com.personal.gateway.flinkAllCommand.configurationOption.ConfigurationOption;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.personal.gateway.flinkAllCommand.configurationOption.webObjectGenerator.AbstractWebObjectGenerator.webElementIdRecode;

/**
 * @author BigHead
 * @date 2022/1/10 16:33
 * @description ConfigurationTypeClassInterface
 */
@Slf4j
public abstract class AbstractConfigurationTypeClass {

    /**
     * 校验先决条件
     *
     * @param configurationOption 先决条件参数
     * @return 返回知否匹配
     */
    public boolean checkAntecedent(ConfigurationOption<?, ?> configurationOption) {
        return true;
    }

    /**
     * 获取对象内所有ConfigurationOption类型参数
     *
     * @param clazz 对应class
     * @return 返回列表
     */
    private List<ConfigurationOption<?, ?>> listConfigurationOptionAllField(Class<?> clazz) {
        List<ConfigurationOption<?, ?>> configurationOptionList = new ArrayList<>();

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            try {
                Object tempObj = field.get(this);
                if (tempObj.getClass().equals(ConfigurationOption.class)) {
                    configurationOptionList.add(
                            (ConfigurationOption<?, ?>) field.get(this)
                    );
                }
            } catch (IllegalAccessException e) {
                log.error("", e);
            }
        }
        if (null != clazz.getSuperclass()) {
            configurationOptionList.addAll(listConfigurationOptionAllField(clazz.getSuperclass()));
        }
        return configurationOptionList;
    }

    /**
     * @param inputParameter 外部输入参数
     * @return 获取页面字符串
     */
    public String getWebElement(JSONObject inputParameter) {
        List<String> webElementList = new ArrayList<>();
        Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> groupOrderMap = sortWebElement(inputParameter);

        for (Integer groupIndexNum : groupOrderMap.keySet().stream().sorted().collect(Collectors.toList())) {
            boolean isFirst = true;
            for (Integer keyIndexNum : groupOrderMap.get(groupIndexNum).keySet().stream().sorted().collect(Collectors.toList())) {
                for (ConfigurationOption<?, ?> configurationOption : groupOrderMap.get(groupIndexNum).get(keyIndexNum)) {
                    webElementList.add(
                            configurationOption.getWebElement(isFirst)
                    );
                    isFirst = false;
                }
            }
        }
        return String.join("\n", webElementList);
    }

    /**
     * 写入参数
     *
     * @param configurationOption 参数类型
     * @param inputParameter      外部输入参数
     *                            TODO 多层深度嵌套目前有问题
     */
    private void setParameter(ConfigurationOption<?, ?> configurationOption, JSONObject inputParameter) {
        if (inputParameter.size() > 0) {
            configurationOption.setValue(
                    inputParameter.getString(
                            webElementIdRecode(
                                    configurationOption.getConfigurationKey().getName()
                            )
                    )
            );
        }
    }

    /**
     * 获取页面元素
     *
     * @return 页面元素字符串
     */
    public Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> sortWebElement(JSONObject inputParameter) {

        List<ConfigurationOption<?, ?>> configurationOptionList = listConfigurationOptionAllField(this.getClass());

        Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> groupOrderMap = new HashMap<>(5);
        for (ConfigurationOption<?, ?> configurationOption : configurationOptionList) {
            if (configurationOption.isHasChildConfigurations()) {
                // 没有前提筛选条件的对象
                if (null == configurationOption.getAntecedentConfigurationOption()) {
                    AbstractConfigurationTypeClass abstractConfigurationTypeClass = (AbstractConfigurationTypeClass) configurationOption.getConfigurationType().getValue();
                    Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> childGroupOrderMap = abstractConfigurationTypeClass.sortWebElement(inputParameter);

                    mergeChildWebElementMap(
                            groupOrderMap,
                            childGroupOrderMap
                    );
                }
                // 有前提筛选条件的对象，且前体筛选条件有值
                if (
                        null != configurationOption.getAntecedentConfigurationOption() &&
                                null != configurationOption.getAntecedentConfigurationOption().getConfigurationType().getValue()
                ) {
                    AbstractConfigurationTypeClass abstractConfigurationTypeClass = ((ConfigurationTypeClass) configurationOption.getConfigurationType()).getValue(configurationOption.getAntecedentConfigurationOption());
                    // 这里出现null是因为前提条件没有选择，或者没有匹配的数据
                    if (null != abstractConfigurationTypeClass) {
                        Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> childGroupOrderMap = abstractConfigurationTypeClass.sortWebElement(inputParameter);

                        mergeChildWebElementMap(
                                groupOrderMap,
                                childGroupOrderMap
                        );
                    }
                }
            } else {
                setParameter(configurationOption, inputParameter);

                mergeOwnerWebElement(
                        groupOrderMap,
                        configurationOption
                );
            }
        }
        return groupOrderMap;
    }

    /**
     * 合并下游页面元素数据
     *
     * @param groupOrderMap      此对象内已存在的页面元素
     * @param childGroupOrderMap 下游页面元素数据
     */
    private void mergeChildWebElementMap(
            Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> groupOrderMap,
            Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> childGroupOrderMap
    ) {
        for (Map.Entry<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> childGroupMapEntry : childGroupOrderMap.entrySet()) {

            Map<Integer, List<ConfigurationOption<?, ?>>> keyOrderMap = groupOrderMap
                    .getOrDefault(
                            childGroupMapEntry.getKey(),
                            new HashMap<>(childGroupMapEntry.getValue().size())
                    );
            for (Map.Entry<Integer, List<ConfigurationOption<?, ?>>> childCustomMapEntry : childGroupMapEntry.getValue().entrySet()) {
                List<ConfigurationOption<?, ?>> defaultOrderList = keyOrderMap
                        .getOrDefault(
                                childCustomMapEntry.getKey(),
                                new ArrayList<>()
                        );
                defaultOrderList.addAll(childCustomMapEntry.getValue());

                keyOrderMap.put(
                        childCustomMapEntry.getKey(),
                        defaultOrderList
                );
            }
            groupOrderMap.put(
                    childGroupMapEntry.getKey(),
                    keyOrderMap
            );
        }
    }

    /**
     * 合并此对象内的页面元素
     *
     * @param groupOrderMap       此对象内已存在的页面元素
     * @param configurationOption 此对象未合并的页面元素
     */
    private void mergeOwnerWebElement(
            Map<Integer, Map<Integer, List<ConfigurationOption<?, ?>>>> groupOrderMap,
            ConfigurationOption<?, ?> configurationOption
    ) {
        Map<Integer, List<ConfigurationOption<?, ?>>> keyOrderMap =
                groupOrderMap
                        .getOrDefault(
                                configurationOption.getGroupKey().getIndexNum(),
                                new HashMap<>(5)
                        );

        List<ConfigurationOption<?, ?>> defaultOrderList =
                keyOrderMap
                        .getOrDefault(
                                configurationOption.getConfigurationKey().getIndexNum(), new ArrayList<>()
                        );


        defaultOrderList.add(configurationOption);

        keyOrderMap.put(
                configurationOption.getConfigurationKey().getIndexNum(),
                defaultOrderList
        );

        groupOrderMap.put(
                configurationOption.getGroupKey().getIndexNum(),
                keyOrderMap
        );
    }

}
